Throwaway: conc-64 gsm8k eval for DEP8+MTP3 dispatch token bug#1659
Throwaway: conc-64 gsm8k eval for DEP8+MTP3 dispatch token bug#1659Oseltamivir wants to merge 18 commits into
Conversation
|
/sweep |
|
@Oseltamivir Kicking off a sweep. Run: https://github.com/SemiAnalysisAI/InferenceX/actions/runs/26905833527 |
…en corruption Narrow dsr1-fp4-mi355x-sglang-disagg-8k1k-mtp search-space to a single DEP8+MTP3 conc-64 entry. With max(CONC_LIST)=64, the server computes SGLANG_MORI_NUM_MAX_DISPATCH_TOKENS_PER_RANK=32, which is below the 256 threshold that selects the correct All2All kernel. Expected: ~0% gsm8k (silent corruption from the low-latency All2All variant). Not for merge — throwaway validation of the dispatch token bug.
93c050e to
45f69f5
Compare
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26905903283 |
Clamp MORI_MAX_DISPATCH_TOKENS_DECODE to minimum 256 when DP+EP are both enabled, preventing SGLang's low-latency All2All kernel from being selected. That kernel silently corrupts outputs at small buffer sizes. Run A of A/B test: benchmark + eval WITH clamp on conc-64 DEP8+MTP3.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26912330265 |
Run B of A/B test: benchmark + eval WITHOUT dispatch token clamp. MORI_MAX_DISPATCH_TOKENS_DECODE will be 32 (<256 threshold). Expected: corrupted output, inflated AL, ~0% gsm8k.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26913235190 |
… benchmark+eval at conc-64 Validates Option A: instead of clamping the env var, patch the installed SGLang moriep.py at runtime to enforce a minimum of 64 (AMD CDNA3/4 warpSize) on num_max_dispatch_tokens_per_rank before it reaches the MoRI kernel config. If gsm8k recovers (like the 256 clamp did), this confirms warpSize is the minimum viable buffer floor and scopes the upstream fix.
…val at conc-64 Root cause: the MoRI All2All dispatch kernel (EpDispatchInterNodeV1Kernel / IntraNode) writes dispatched tokens into warpSize-aligned receive slots (destTokId = flagSlotId*warpSize + laneId, laneId 0..63), so each warp-chunk spans 64 (CDNA3/4 wavefront) token slots. The per-rank receive region is sized to maxNumInpTokenPerRank, which the harness derives as max(CONC_LIST)/TP*(MTP+1). At low concurrency this collapses below 64 (conc-64/TP8/MTP3 -> 64/8*4 = 32), so a single chunk overruns the 32-slot region -> silent out-of-bounds writes -> semantically corrupt output (decodes fine, gsm8k=0). Confirmed from the conc-64 Run B decode log: INTER_KERNEL_SWITCH=16 with DISPATCH_TOKENS=32 selects the NON-LL InterNodeV1 kernel (32 > 16), yet output was still corrupt -> the bug is the buffer-size floor, not the LL-vs-non-LL kernel choice. Fix: clamp MORI_MAX_DISPATCH_TOKENS_DECODE to >= 64 after the MTP multiply. Only raises the value at low conc; adds a few MB of staging buffer but no compute, so real throughput is unchanged (the ~3% edge of the corrupt run was an artifact of dropping work). 64 is the principled minimum vs the proven-but- larger 256.
…-eval # Conflicts: # perf-changelog.yaml
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26919517564 |
…ent) The conc-64 run with the warpSize floor (64) still scored gsm8k=0.00 (run 26919517564), disproving the one-wavefront hypothesis. The per-rank dispatch buffer must hold the routing fan-in (a receiving rank takes tokens from all worldSize peers), not just one warp-chunk. Empirically on MI355X: dispatch=32 -> 0.00, dispatch=64 -> 0.00, dispatch>=256 -> 0.94. Clamp to the proven 256. Throughput is unchanged; the corrupt run's ~3% edge was dropped work, not real speed.
The vendor image installs sglang as a namespace package where __file__ is None. os.path.dirname(None) throws TypeError, so the patcher crashed and the floor was never applied — eval ran unpatched. Fall through __file__ → __path__ → importlib.util.find_spec() to locate the package directory robustly.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26925858550 |
66d701b to
9b50d69
Compare
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26930095670 |
The vendor image installs sglang at /sgl-workspace/sglang/ but the actual Python package is under python/sglang/ within that tree. When __path__ returns the repo root, the patcher couldn't find moriep.py. Add candidate paths and a bounded walk fallback.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26933055265 |
| f"{indent} self.num_max_dispatch_tokens_per_rank, {FLOOR}\n" | ||
| f"{indent})\n" | ||
| ) | ||
| lines.insert(end + 1, floor_block) |
There was a problem hiding this comment.
Unbalanced parens corrupt moriep insert
Low Severity
If parenthesis balancing never reaches depth <= 0 before EOF, end stays at start and the floor block is inserted on the line after the opening get_int_env_var(, which can splice Python inside a multi-line call and break moriep.py without reporting failure.
Reviewed by Cursor Bugbot for commit 59dd6c3. Configure here.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26933060562 |
The formula divided BENCH_MAX_CONC_VALUE by decode_dp_ranks, assuming --max-running-requests is a global limit split across DP ranks. It is actually per-rank: each of the 8 DP schedulers independently allows up to BENCH_MAX_CONC_VALUE requests. At conc-64/TP8/MTP3 the old formula produced dispatch=32 (64/8*4), but each rank can hold 64*4=256 tokens, causing 8x buffer overflow in MoRI's intra-node dispatch kernel (the only guard is an assert compiled out under -DNDEBUG) and silent corruption (gsm8k=0).
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 3 total unresolved issues (including 2 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1fdb89f. Configure here.
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=26933589129 |
|
see unofficial run visualizer at https://inferencex.semianalysis.com/inference?unofficialRun=27217039296 |


Summary
SGLANG_MORI_NUM_MAX_DISPATCH_TOKENS_PER_RANK< 256 silent corruption on DEP8+MTP3 disagg configdsr1-fp4-mi355x-sglang-disagg-8k1k-mtpsearch-space to a single conc-64 DEP8+MTP3 entrymax(CONC_LIST)=64, server computesdispatch_tokens = 64/8*4 = 32(below 256 threshold → broken All2All kernel)Background
The previous eval (#1644) passed with 0.9431 gsm8k because the conc-list was
[64,128,256,512,640]→max=640→dispatch_tokens=320(≥256, correct kernel). The actual perf benchmarks run each concurrency point solo, so at conc=64 the value drops to 32 → broken kernel → garbage tokens + inflated AL.Not for merge — throwaway validation only.
Note
Medium Risk
Mutates installed sglang at container start and changes MoRI sizing for all disagg runs using
server_sglang.sh; benchmark correctness improves but behavior diverges from unpatched upstream until merged.Overview
Adds a MoRI dispatch-token fix for low-concurrency DEP8+MTP3 disagg runs where tiny
SGLANG_MORI_NUM_MAX_DISPATCH_TOKENS_PER_RANKvalues (e.g. conc-64 → 32) silently corrupt MoE output (gsm8k ≈ 0).Harness / server:
server_sglang.shnow runsapply_moriep_dispatch_floor.pybeforelaunch_server, which in-place patches the image’s vendormoriep.pyto floornum_max_dispatch_tokens_per_rankat 256 (avoids a full-file overlay that breaksMoriEPDispatcher). The DP+EP decode path setsMORI_MAX_DISPATCH_TOKENS_DECODEtoBENCH_MAX_CONC_VALUE(per DP rank), notmax_conc / dp_ranks, and drops the old harness env clamp in favor of the sglang-side floor.patches/README.mdandperf-changelog.yamldocument the behavior.CI config (marked throwaway):
dsr1-fp4-mi355x-sglang-disagg-8k1k-mtp8k1k MTP search-space is collapsed to a single conc-64, 1×DEP8 prefill/decode, MTP3 entry to reproduce dispatch=32 corruption on MI355X.Reviewed by Cursor Bugbot for commit 1f386bd. Bugbot is set up for automated code reviews on this repo. Configure here.